package com.leizhi.demo.monitor.service.impl;

import com.leizhi.demo.monitor.achieve.PushStreamService;
import com.leizhi.demo.monitor.cache.TokenCache;
import com.leizhi.demo.monitor.pojo.PushStreamProcessInfo;
import com.leizhi.demo.monitor.pojo.SrsCallbackDto;
import com.leizhi.demo.monitor.pojo.SrsCallbackDvrDto;
import com.leizhi.demo.monitor.service.SrsService;
import com.leizhi.demo.monitor.utils.TokenUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.Map;

@Service
public class SrsServiceImpl implements SrsService {

    private static final Logger logger = LoggerFactory.getLogger(SrsServiceImpl.class);

    /* 记录每个流的播放人数 */
    private final Map<String, Integer> streamMap = new HashMap<>();

    @Autowired
    private TokenCache tokenCache;
    @Autowired
    private PushStreamService pushStreamService;


    @Override
    public void onPlay(SrsCallbackDto dto) {
        String param = dto.getParam();
        if (param == null || !param.startsWith("?token=")) {
            throw new RuntimeException("未携带鉴权 Token");
        }

        String token = param.substring(7);
        if (!tokenCache.exist(token) || !TokenUtil.verify(token)) {
            throw new RuntimeException("鉴权 Token 不存在或者无效");
        }

        Integer number = streamMap.get(dto.getStreamId());
        if (number == null) {
            streamMap.put(dto.getStreamId(), 1);
            return;
        }
        streamMap.put(dto.getStreamId(), number + 1);
    }

    @Override
    public void onStop(SrsCallbackDto dto) {
        Integer number = streamMap.get(dto.getStreamId());
        if (number == null) {
            return;
        }

        int newNumber = number - 1;
        if (newNumber != 0) {
            streamMap.put(dto.getStreamId(), newNumber);
            return;
        }

        pushStreamService.stop(getSsrc(dto.getStream()));
        streamMap.remove(dto.getStreamId());
    }

    @Override
    public void dvr(SrsCallbackDvrDto dto) {
        Long ssrc = Long.parseLong(getSsrc(dto.getStream()));
        Path sourcePath = Paths.get(dto.getFile());

        try {
            PushStreamProcessInfo process = pushStreamService.getProcess(ssrc);
            if (process == null || !process.isCloud()) {  // 推流不存在，或者不是云存储，则删除文件
                Files.delete(sourcePath);
                return;
            }

            // 目前只在本地操作，后续需要上传到阿里云存储
            String fileName = dto.getFile().replace(dto.getStream(), process.getDeviceId());
            Path targetPath = Paths.get(fileName);
            Files.move(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            logger.error("在录像 DVR 中对文件更改发生了错误，Stream：{}，错误信息：{}", dto.getStream(), e.getMessage());
            throw new RuntimeException(e.getMessage());
        }
    }

    private String getSsrc(String stream) {
        int dashIndex = stream.indexOf("-");
        return stream.substring(dashIndex + 1);
    }

}
